﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
//using AddInRuleSetTest1;
using System.IO;
using Microsoft.VisualStudio.Shell.Interop;
using System.Xml;
using System.Xml.XPath;
using System.Text.RegularExpressions;


namespace RuleXSoft.BizRuleCreator
{
    public partial class BizRuleGenerater : Form
    {
        public event EventHandler OnRuleXGenerated;
        //public event EventHandler<RulXEventArgs> OnRuleXUpdated;

        public delegate void RulXEventHandler(object sender, RulXEventArgs args);
        public event RulXEventHandler OnRuleXUpdated;

        private BizRuleMapper objBizRuleMapper = null;
        private ClassGenerator objClassGen = null;
        public string NameSpace { get; set; }
        public string ClassName { get; set; }
        public string ClassNameForUpdate { get; set; }
        public string OutputAttributeFileName { get; set; }
        public string OutputDir { get; set; }
        public string ActiveSolutionFullName { get; set; }
        public string RulesetFileName { get; set; }
        public string SelectedProjectType   { get; set; }
        public int DialogOpeningMode { get; set; }

        public string RulXFileNameForUpdate { get; set; }


        public List<string> ExistingRulXFileList { get; set; }

        private ExcelObject objExcel = null;

        private DataSet dsExcelAtt = null;

        private const string rulXFileNamePrefix = @"RulXItem";
        private const string rulXAttributeClassNamePrefix = @"RulXItem";
        //private VSHelper objVSHelper = null;
        //private Connect objVSConnectHelper = null;

        string strSystemRoot = Environment.GetEnvironmentVariable("SystemRoot");

        private const string tempOutputDir = @"C:\Windows\Temp\BizRuleGen";
        //string tempOutputDir = string.Empty;
        private const string xsdFileName = @"XmlRuleSetSchema.xsd";

        public int iRuleSelectionOption { get; set; }

        public BizRuleGenerater()
        {
            InitializeComponent();
            objBizRuleMapper = new BizRuleMapper();
            dsExcelAtt = new DataSet();
            //objVSHelper = new VSHelper();
            //objVSConnectHelper = new Connect();
            //string tempOutputDir = strSystemRoot + @"\Temp\BizRuleGen";
            //this.dgvBizRuleMapper.DataError += new DataGridViewDataErrorEventHandler(dgvBizRuleMapper_DataError);
            if (this.DialogOpeningMode == 0)
            {
                this.txtOutputDir.Text = tempOutputDir;
                SetInitialRulXFileNames(); 
            }
            else if (this.DialogOpeningMode == 1)
            {
                this.tabOption.TabPages.RemoveAt(1);
            }

            tabOption.TabIndexChanged+=new EventHandler(tabOption_TabIndexChanged);
        }

        void dgvBizRuleMapper_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {
            //throw new NotImplementedException();
        }

        private void SetInitialRulXFileNames()
        {
            int initialFileSuffix = 1;
            this.txtAttributeFileName.Text = rulXAttributeClassNamePrefix + initialFileSuffix;
            this.txtRulesetFileName.Text = rulXFileNamePrefix + initialFileSuffix;
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            //PrepareFileDialog();
            ExecuteRxcelFileDialog();

        }

        private void PrepareFileDialog()
        {
            try
            {
                OpenFileDialog fDialog = new OpenFileDialog();
                fDialog.Title = "Open Excel File";

                fDialog.Filter = "xls Files|*.xls|xlsx Files|*.XLS";

                fDialog.InitialDirectory = @"K:\";

                if (fDialog.ShowDialog() == DialogResult.OK)
                {
                    //MessageBox.Show(fDialog.FileName.ToString());
                    txtExcelPath.Text = fDialog.FileName.ToString();
                }
            }
            catch (Exception ex)
            {
                
                MessageBox.Show(ex.Message);
            }
        }

        private void ExecuteRxcelFileDialog()
        {
            try
            {
                string strExcelFileName = string.Empty;

                dlgOpenFile.Filter = "Excel File(*.xls)|*.xls";
                dlgOpenFile.ShowDialog();
                strExcelFileName = dlgOpenFile.FileName;
                objExcel = new ExcelObject(strExcelFileName, false);
                txtExcelPath.Text = strExcelFileName;
                string[] sheetnames = objExcel.GetExcelSheetNames();
                cboSheetName.Items.Clear();
                cboSheetName.Items.AddRange(sheetnames);
                cboSheetName.SelectedIndex = 0;
            }
            catch (ArgumentOutOfRangeException ex)
            {
                this.txtExcelPath.Text = "";
                MessageBox.Show("You must select an RulX Excel file");
                
            }
            catch (Exception ex)
            {
                
                MessageBox.Show(ex.Message);
            }
        }

        private void PrepareMappingAttributes()
        {
            
            List<string> objExcelAttList = new List<string>();
            List<string> objXMLAttList = new List<string>();

            DataTable dtBizAttMap = new DataTable();


            dtBizAttMap = objBizRuleMapper.GetAttributesForMapping(objExcelAttList, objXMLAttList);
            //dgvBizRuleMapper.DataSource = dtBizAttMap;



        }

        private void SetRulXFileNameAfterValidation()
        {
            string strRulXFile = this.txtRulesetFileName.Text;
            string strRulXAttributeClassFile = this.txtAttributeFileName.Text;

            int maxRulXFileNameSuffixNo = 0;
            int rulXFileNamesuffixNo = 0;
            int maxRulXClassNameSuffixNo = 0;
            int rulXClassNamesuffixNo = 0;
            if (ExistingRulXFileList != null && ExistingRulXFileList.Count>0)
            {
                foreach (string fileItem in ExistingRulXFileList)
                {
                    if (fileItem.EndsWith(".rulx"))
                    {
                        int fileDotIndex = fileItem.IndexOf('.');

                        if (fileItem.Substring(0, rulXFileNamePrefix.Length).Equals(rulXFileNamePrefix))
                        {
                            rulXFileNamesuffixNo = Convert.ToInt32(fileItem.Substring(rulXFileNamePrefix.Length, fileDotIndex - rulXFileNamePrefix.Length));
                            if (rulXFileNamesuffixNo > maxRulXFileNameSuffixNo)
                            {
                                maxRulXFileNameSuffixNo = rulXFileNamesuffixNo;
                            }
                        }

                    }
                    else
                    {
                        int fileDotIndex = fileItem.IndexOf('.');

                        if (fileItem.Substring(0, rulXAttributeClassNamePrefix.Length).Equals(rulXAttributeClassNamePrefix))
                        {
                            rulXClassNamesuffixNo = Convert.ToInt32(Convert.ToInt32(fileItem.Substring(rulXAttributeClassNamePrefix.Length, fileDotIndex - rulXAttributeClassNamePrefix.Length)));
                            if (rulXClassNamesuffixNo > maxRulXClassNameSuffixNo)
                            {
                                maxRulXClassNameSuffixNo = rulXClassNamesuffixNo;
                            }
                        }
                    }
                } 
            }

            maxRulXFileNameSuffixNo++;
            maxRulXClassNameSuffixNo++;

            this.txtRulesetFileName.Text = rulXFileNamePrefix + maxRulXFileNameSuffixNo;
            this.txtAttributeFileName.Text = rulXAttributeClassNamePrefix + maxRulXClassNameSuffixNo;


        }

        private void AddNewRulXSet()
        {
            OutputAttributeFileName = txtAttributeFileName.Text.Trim();
            RulesetFileName = txtRulesetFileName.Text.Trim();
            OutputDir = txtOutputDir.Text;
            //Create the temp output directory
            CreateTempDirForOutput();
            CopyXSDFile(xsdFileName);
            //Asdsign the Class name provided by the Converter tool
            this.ClassName = txtAttributeFileName.Text.Trim();
            //Generate the final input xml file
            GenerateFinalXML(string.Empty, ClassName);
            //Generate the Atribute Class
            List<string> propNameList = new List<string>();
            foreach (DataColumn dc in dsExcelAtt.Tables[0].Columns)
            {
                if (!dc.ColumnName.Trim().ToUpper().Substring(0, 8).Equals("EXCLUDE_"))
                {
                    propNameList.Add(dc.Caption);
                }
            }
            //GenerateAttributeClass(propNameList, this.SelectedProjectType);
            this.btnCancel.Text = "Finish";
            //Clear the grid
            if (OnRuleXGenerated != null)
            {
                OnRuleXGenerated(this, EventArgs.Empty);
            }
            dgvBizRuleMapper.Rows.Clear();
            //string btnFinishCaption = GetResourceString("@113");

            MessageBox.Show("RulX Item successfully created.");
            this.Close();
        }

        private IList<RulXAttribute> PrepareFinalListFromRulXForUpdate(DataGridView dgvRulXForUpdate)
        {
            IList<RulXAttribute> listRulXObjectFields = new List<RulXAttribute>();
            int rowCount = 0;

            foreach (DataGridViewRow row in dgvRulXForUpdate.Rows)
            {
                if (rowCount == dgvRulXForUpdate.Rows.Count-1)
                {
                    break;
                }
                RulXAttribute objRulXAtt = new RulXAttribute();

                objRulXAtt.RulXFieldName = row.Cells["xMLFields"].Value.ToString();
                objRulXAtt.RulXFieldDataType = row.Cells["DataType"].Value.ToString();
                objRulXAtt.RulXFieldDirection = row.Cells["Direction"].Value.ToString();

                listRulXObjectFields.Add(objRulXAtt);
                rowCount++;
            }

            return listRulXObjectFields;
        }

        private RulesetObject PrepareListFromRulesetForUpdate(string strRulXFile)
        {
            //Procedure to perse the XML document and find appropriate element / attribute in order to build the Attribute class
            //Find the Class name

            

            RulesetObject objRuleset = new RulesetObject();
            //Load the XML file
            XmlDocument doc = new XmlDocument();
            //We have already validated the XML. No XmlException can be thrown here
            doc.Load(strRulXFile);

            string rulXRulesetName = string.Empty;

            rulXRulesetName = doc.SelectSingleNode("/Types/RuleSetName/@text").Value;
            objRuleset.RulesetName = rulXRulesetName;

            string rulXRulesetDesc = string.Empty;

            rulXRulesetDesc = doc.SelectSingleNode("/Types/RuleSetDescription/@text").Value;
            objRuleset.RulesetDescription = rulXRulesetDesc;

            string rulXClassName = string.Empty;
            //rulXClassName = nodeWithClassName.Current.GetAttribute("name", string.Empty);

            rulXClassName = doc.SelectSingleNode("/Types/RuleSetClass/@name").Value;
            objRuleset.RulesetAttributeClassName = rulXClassName;

            objRuleset.RulesetFileName = Path.GetFileName(strRulXFile);


            return objRuleset;
        }

        private IList<RulXAttribute> PrepareListFromRulXForUpdate(string strRulXFile)
        {
            //Procedure to perse the XML document and find appropriate element / attribute in order to build the Attribute class
            //Find the Class name

            DataSet dsRulXForUpdate = new DataSet();
            

            //Load the XML file
            XmlDocument doc = new XmlDocument();
            //We have already validated the XML. No XmlException can be thrown here
            doc.Load(strRulXFile);

            string rulXClassName = string.Empty;
            //rulXClassName = nodeWithClassName.Current.GetAttribute("name", string.Empty);

            rulXClassName = doc.SelectSingleNode("/Types/RuleSetClass/@name").Value;

            this.ClassNameForUpdate = rulXClassName;

            XPathNavigator navigatorForFields = doc.CreateNavigator();
            XPathNodeIterator nodeWithFields = navigatorForFields.Select("Types/RuleSetClass/Declaration/Fields");

            IList<RulXAttribute> listRulXObjectFields = new List<RulXAttribute>();

            XmlNodeList fieldNodeList;
            //fieldNodeList = doc.SelectNodes("Types/RuleSetClass/Declaration/Fields/Field/@name");

            fieldNodeList = doc.SelectNodes("Types/RuleSetClass/Declaration/Fields/Field");

            foreach (XmlNode nodeItem in fieldNodeList)
            {
                RulXAttribute objRulXAtt = new RulXAttribute();
                objRulXAtt.RulXFieldName = nodeItem.Attributes["name"].InnerText;
                objRulXAtt.RulXFieldDataType = nodeItem.Attributes["type"].InnerText;
                objRulXAtt.RulXFieldDirection = nodeItem.Attributes["direction"].InnerText;
                if (nodeItem.Attributes["derived"].InnerText.Trim().ToUpper().Equals("DERIVED"))
                {
                    objRulXAtt.IsDerived = true;
                }
                else
                {
                    objRulXAtt.IsDerived = false;
                }

                if (nodeItem.Attributes["allownull"].InnerText.Trim().ToUpper().Equals("TRUE"))
                {
                    objRulXAtt.IsAllowedNull = true;
                }
                else
                {
                    objRulXAtt.IsAllowedNull = false;
                }

                listRulXObjectFields.Add(objRulXAtt);
            }



             return listRulXObjectFields;
        }

        private void UpdateExistingRulXSet(string strRulXFileName, string strRulXClassName)
        {
            //OutputAttributeFileName = txtAttributeFileName.Text.Trim();
            RulesetFileName = strRulXFileName.Trim();
            OutputDir = txtOutputDir.Text;
            //Create the temp output directory
            CreateTempDirForOutput();
            CopyXSDFile(xsdFileName);
            //Asdsign the Class name provided by the Converter tool
            this.ClassName = strRulXFileName.Trim();
            //strRulXClassName = this.ClassNameForUpdate;
            //Generate the final input xml file
            GenerateFinalXML(strRulXFileName, strRulXClassName);
            
            this.btnCancel.Text = "Finish";
            //Clear the grid
            if (OnRuleXUpdated != null)
            {
                RulXEventArgs objRulXEventArgs = new RulXEventArgs(strRulXFileName);

                OnRuleXUpdated(this, objRulXEventArgs);
            }
            dgvBizRuleMapper.Rows.Clear();
            //string btnFinishCaption = GetResourceString("@113");

            MessageBox.Show("RulX Item successfully Updated.");
            this.Close();
        }

        private void btnGenerate_Click(object sender, EventArgs e)
        {

            try
            {
                if (ValidateInput())
                {
                    if (this.DialogOpeningMode == 0)
                    {
                        AddNewRulXSet();
                    }
                    else if (this.DialogOpeningMode == 1)
                    {
                        UpdateExistingRulXSet(this.RulXFileNameForUpdate, this.ClassNameForUpdate);
                    }
                }
                else
                {
                    MessageBox.Show("Mandatory input required...","Validation Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
                }
                
            }
            catch (Exception ex)
            {
                
                //MessageBox.Show(ex.Message);
                errLabel.Text = ex.Message + Environment.NewLine + ex.StackTrace;
            }
        }

        private bool ValidateInput()
        {
            bool bResult=false;

            if (string.IsNullOrEmpty(this.txtAttributeFileName.Text)
                || string.IsNullOrEmpty(this.txtAttributeFileName.Text)
                || string.IsNullOrEmpty(this.txtRulesetFileName.Text)
                || string.IsNullOrEmpty(this.txtRulesetName.Text)
                || string.IsNullOrEmpty(this.txtRulesetDesc.Text))
            {
                bResult = false;
            }
            else
            {
                bResult = true;
            }

            return bResult;
        }

        private BizRuleXVS2010Package myPackage;
        /// <summary>
        /// This method loads a localized string based on the specified resource.
        /// </summary>
        /// <param name="resourceName">Resource to load</param>
        /// <returns>String loaded for the specified resource</returns>
        internal string GetResourceString(string resourceName)
        {
            string resourceValue;
            IVsResourceManager resourceManager = (IVsResourceManager)GetService(typeof(SVsResourceManager));
            if (resourceManager == null)
            {
                throw new InvalidOperationException("Could not get SVsResourceManager service. Make sure the package is Sited before calling this method");
            }
            Guid packageGuid = myPackage.GetType().GUID;
            int hr = resourceManager.LoadResourceString(ref packageGuid, -1, resourceName, out resourceValue);
            Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(hr);
            return resourceValue;
        }

        private void CopyXSDFile(string xsdFileName)
        {
            try
            {
                
                //File.Copy(
            }
            catch (Exception ex)
            {
                
                MessageBox.Show("Error copying XSD file...");
            }
        }

        private void GenerateAttributeClass(List<string> propNameList, string selectedProjType)
        {
            try
            {
                string fileName = string.Empty;
                if (selectedProjType.Equals(".csproj"))
                {
                    fileName = OutputDir + @"\" + OutputAttributeFileName + @".cs"; 
                }
                else if (selectedProjType.Equals(".vbproj"))
                {
                    fileName = OutputDir + @"\" + OutputAttributeFileName + @".vb";
                }
                else if (selectedProjType.Equals(".jsproj"))
                {
                    fileName = OutputDir + @"\" + OutputAttributeFileName + @".js";
                }
                else
                {
                    fileName = OutputDir + @"\" + OutputAttributeFileName + @".cs";
                }
                NameSpace = "BizRuleCreator";
                ClassName = OutputAttributeFileName;
                objClassGen = new ClassGenerator(NameSpace, ClassName, selectedProjType);

                List<string> propertyList = new List<string>();

                foreach (string item in propNameList)
                {
                    IList<string> listPropName = item.Split('|');
                    string strfieldName = "_f" + listPropName[0].ToString();
                    string strPropName = listPropName[0].ToString();
                    string strdirection = listPropName[1].ToString();
                    string strdataType = listPropName[2].ToString();

                    bool directionPath = false;

                    Type type;
                    if(strdataType.Equals("string"))
                    {
                        type = typeof(string);
                    }
                    else if(strdataType.Equals("int"))
                    {
                        type = typeof(int);
                    }
                    else if(strdataType.Equals("double"))
                    {
                        type = typeof(double);
                    }
                    else if(strdataType.Equals("datetime"))
                    {
                        type = typeof(DateTime);
                    }
                    else if (strdataType.Equals("boolean"))
                    {
                        type = typeof(bool);
                    }
                    else
                    {
                        type = typeof(string);
                    }

                    if (strdirection.ToUpper().Equals("OUTPUT"))
                    {
                        directionPath = true;
                    }
                    else
                    {
                        directionPath = false;
                    }

                    objClassGen.AddFields("_f" + strPropName, type);

                    objClassGen.AddProperties(strPropName, strfieldName, type, directionPath);

                    propertyList.Add(strPropName + "|" + strdirection);
                }
                objClassGen.AddMethod(propertyList, ClassName, selectedProjType);
                objClassGen.GenerateCSharpCode(fileName);
            }
            catch (Exception ex)
            {
                
                throw ex;
            }
        }

        private DataTable AddAditionalXmlAttribute(DataSet dsFinalXml)
        {
            try
            {
                DataTable dtAdditionalXmlAtt = new DataTable();

                dtAdditionalXmlAtt.Columns.Add("directionCol");
                dtAdditionalXmlAtt.Columns.Add("dataTypeCol");
                foreach (DataGridViewRow dgvr in dgvBizRuleMapper.Rows)
                {
                    dtAdditionalXmlAtt.Rows.Add(dgvr.Cells["Direction"].Value.ToString(),dgvr.Cells["DataType"].Value.ToString());
                }
                return dtAdditionalXmlAtt;
            }
            catch (Exception ex)
            {

                throw ex;
                
            }
        }

        private void GenerateFinalXML(string strRulXFileName, string strRulXClassName)
        {

            RulesetObject objRuleset = new RulesetObject();
            objRuleset.RulesetFileOutputDirectory = tempOutputDir;
            objRuleset.RulesetFileName = RulesetFileName;
            objRuleset.RulesetAttributeClassName = strRulXClassName;
            objRuleset.RulesetName = this.txtRulesetName.Text.Trim();
            objRuleset.RulesetDescription = this.txtRulesetDesc.Text.Trim();
            
            
            if (this.DialogOpeningMode == 0)
            {
                //Replacing proper xml element name against excel field name
                GenerateObjectPropertyName(dsExcelAtt, 0);

                

                //Generate the final input xml file
                objBizRuleMapper.GenerateXML(dsExcelAtt, objRuleset); 
            }
            else if (this.DialogOpeningMode == 1)
            {
                //Populate all the existing records (ruleset rows)
                objRuleset.RulesetFileOutputDirectoryForUpdate = Path.GetDirectoryName(strRulXFileName);
                
                DataSet dsRulX = new DataSet();
                dsRulX = PopulateRulXForUpdate(RulesetFileName);

                //Replacing proper xml element name against excel field name
                GenerateObjectPropertyName(dsRulX, 1);
                //Update the final input xml file
                string strRulXFileDirectoryName = string.Empty;
                string strRulXFileNameFromPath = string.Empty;
                strRulXFileDirectoryName = Path.Combine(Path.GetDirectoryName(strRulXFileName));
                strRulXFileNameFromPath = Path.GetFileName(strRulXFileName);
                objBizRuleMapper.UpdateRulXXML(dsRulX, objRuleset); 
            }
        }

        private DataTable PrepareTempDataSetForRulX(IList<RulXAttribute> listObjRulX)
        {
            DataTable dtTempRulx = new DataTable();

            foreach (RulXAttribute itemObjRulx in listObjRulX)
            {
                dtTempRulx.Columns.Add(new DataColumn(itemObjRulx.RulXFieldName));
            }

            return dtTempRulx;
        }

        private DataSet PopulateRulXForUpdate(string strRulxFileForUpdate)
        {
            try
            {
                //Prepare temporary memory table to hold all existing rulx data
                IList<RulXAttribute> listRulXObjectForUpdate = new List<RulXAttribute>();

                listRulXObjectForUpdate = PrepareFinalListFromRulXForUpdate(this.dgvBizRuleMapper);
                DataTable dtRulxForUpdate = PrepareTempDataSetForRulX(listRulXObjectForUpdate);

                DataSet dsRulXForUpdate = new DataSet();

                //Procedure to perse the XML document and find appropriate element / attribute in order to build the Attribute class
                //Find the Class name

                //Load the XML file
                XmlDocument doc = new XmlDocument();
                //We have already validated the XML. No XmlException can be thrown here
                doc.Load(strRulxFileForUpdate);

                XPathNavigator navigatorForFields = doc.CreateNavigator();
                XPathNodeIterator nodeWithFields = navigatorForFields.Select("Types/RuleSetClass/RuleSet/Rule");

                XmlNodeList fieldRuleNodeList;
                fieldRuleNodeList = doc.SelectNodes("Types/RuleSetClass/RuleSet/Rule");

                foreach (XmlNode nodeRuleItem in fieldRuleNodeList)
                {
                    DataRow rowRulx;
                    rowRulx = dtRulxForUpdate.NewRow();

                    if (nodeRuleItem.HasChildNodes)
                    {
                        int rulXFieldCount = 0;
                        foreach (XmlNode nodeDataItem in nodeRuleItem.ChildNodes)
                        {
                            string rulXFieldName = nodeDataItem.Attributes["key"].Value;
                            
                            //rowRulx[rulXFielName] = nodeDataItem.Attributes["value"].Value;
                            rowRulx[rulXFieldCount] = nodeDataItem.Attributes["value"].Value;
                            rulXFieldCount++;
                        }
                    }

                    dtRulxForUpdate.Rows.Add(rowRulx);
               
                }

                dsRulXForUpdate.Tables.Add(dtRulxForUpdate);

                return dsRulXForUpdate;
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        private void GenerateObjectPropertyName(DataSet ds, int iMode)
        {
            try
            {
                List<string> excludedColumnList = new List<string>();
                //Removing excluded column from dataset

                //if (iMode == 0)
                //{
                    foreach (DataGridViewRow dgvr in dgvBizRuleMapper.Rows)
                    {
                        if (Convert.ToBoolean(dgvr.Cells["Exclude"].Value))
                        {
                            if (iMode == 0)
                            {
                                excludedColumnList.Add(dgvr.Cells["excelFields"].Value.ToString());
                            }
                            else
                            {
                                excludedColumnList.Add(dgvr.Cells["xmlFields"].Value.ToString());
                            }
                        }
                    }  
                //}

                    int icount = 0;

                foreach (DataColumn dc in ds.Tables[0].Columns)
                {
                    foreach (DataGridViewRow dgvr in dgvBizRuleMapper.Rows)
                    {
                        if (!Convert.ToBoolean(dgvr.Cells["Exclude"].Value))
                        {

                            if (iMode == 0)
                            {
                                if (string.Equals(dc.Caption.Trim(), dgvr.Cells[0].Value.ToString().Trim()))
                                {
                                    dc.ColumnName = dgvr.Cells["xMLFields"].Value.ToString().Trim();
                                    dc.ColumnName += "|" + dgvr.Cells["Direction"].Value.ToString() +
                                        "|" + dgvr.Cells["DataType"].Value.ToString();
                                    if (Convert.ToBoolean(dgvr.Cells["Derived"].Value))
                                    {
                                        dc.ColumnName += "|" + "Derived";
                                    }
                                    else
                                    {
                                        dc.ColumnName += "|" + "NotDerived";
                                    }

                                    #region AllowNull implementation
                                    if (Convert.ToBoolean(dgvr.Cells["AllowNull"].Value))
                                    {
                                        dc.ColumnName += "|" + "NullAllowed";
                                    }
                                    else
                                    {
                                        dc.ColumnName += "|" + "NullNotAllowed";
                                    } 
                                    #endregion
                                } 
                            }
                            else if (iMode == 1)
                            {
                                if (dgvr.Cells[0].Value != null)
                                {
                                    if (string.Equals(dc.Caption.Trim(), dgvr.Cells[0].Value.ToString().Trim()))
                                    {
                                        dc.ColumnName = dgvr.Cells["xMLFields"].Value.ToString().Trim();
                                        dc.ColumnName += "|" + dgvr.Cells["Direction"].Value.ToString() +
                                            "|" + dgvr.Cells["DataType"].Value.ToString();
                                        if (Convert.ToBoolean(dgvr.Cells["Derived"].Value))
                                        {
                                            dc.ColumnName += "|" + "Derived";
                                        }
                                        else
                                        {
                                            dc.ColumnName += "|" + "NotDerived";
                                        }

                                        #region AllowNull implementation
                                        if (Convert.ToBoolean(dgvr.Cells["AllowNull"].Value))
                                        {
                                            dc.ColumnName += "|" + "NullAllowed";
                                        }
                                        else
                                        {
                                            dc.ColumnName += "|" + "NullNotAllowed";
                                        }
                                        #endregion
                                    }  
                                }
                            }

                        }
                    }

                    icount++;
                }
                
                foreach (DataColumn dc in ds.Tables[0].Columns)
                {
                    if (excludedColumnList.Contains(dc.Caption.Trim()))
                    {
                        dc.ColumnName = "exclude_" + dc.ColumnName;
                    }
                }
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);
            }
        }

        private void txtExcelPath_TextChanged(object sender, EventArgs e)
        {
            try
            {
                if (txtExcelPath.Text.EndsWith(".xls"))
                {
                    //PopulateInitialMappingGrid();
                }
            }
            catch (Exception ex)
            {
                
                MessageBox.Show(ex.Message);
            }
        }

        private void PrepareGridFrame()
        {
            if (dgvBizRuleMapper.RowCount>0)
            {
                dgvBizRuleMapper.Rows.Clear(); 
            }
            if (dgvBizRuleMapper.Columns.Count > 0)
            {
                dgvBizRuleMapper.Columns.Clear();
            }
            
            if (this.DialogOpeningMode == 0)
            {
                dgvBizRuleMapper.Columns.Add("excelFields", "Excel Fields"); 
            }
            dgvBizRuleMapper.Columns.Add("xMLFields", "XML Fields");

            var directionColumn = new DataGridViewComboBoxColumn()
            {
                Name = "Direction",
                FlatStyle = FlatStyle.Flat,
                DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing
            };
            directionColumn.DataSource = new string[] { "Input", "Output" };
            dgvBizRuleMapper.Columns.Add(directionColumn);



            var dataTypeColumn = new DataGridViewComboBoxColumn()
            {
                Name = "DataType",
                FlatStyle = FlatStyle.Flat,
                DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing
            };
            dataTypeColumn.DataSource = new string[] { "string", "int", "double", "boolean", "DateTime", "List<object>" };
            dgvBizRuleMapper.Columns.Add(dataTypeColumn);

            var isColExcludeColumn = new DataGridViewCheckBoxColumn()
            {
                Name = "Exclude",
                HeaderText = "Exclude",
                FlatStyle = FlatStyle.Flat

            };

            dgvBizRuleMapper.Columns.Add(isColExcludeColumn);

            var isColDerivedColumn = new DataGridViewCheckBoxColumn()
            {
                Name = "Derived",
                HeaderText = "Derived",
                FlatStyle = FlatStyle.Flat

            };

            dgvBizRuleMapper.Columns.Add(isColDerivedColumn);

            var isColAllowNullColumn = new DataGridViewCheckBoxColumn()
            {
                Name = "AllowNull",
                HeaderText = "Allow Nulls",
                FlatStyle = FlatStyle.Flat

            };

            dgvBizRuleMapper.Columns.Add(isColAllowNullColumn);


            
            dgvBizRuleMapper.Columns["xMLFields"].Width = 135;
            dgvBizRuleMapper.Columns["Direction"].Width = 80;
            dgvBizRuleMapper.Columns["DataType"].Width = 80;
            dgvBizRuleMapper.Columns["Exclude"].Width = 50;
            dgvBizRuleMapper.Columns["Derived"].Width = 50;
            dgvBizRuleMapper.Columns["AllowNull"].Width = 50;

            if (this.DialogOpeningMode == 0)
            {
                dgvBizRuleMapper.Columns["excelFields"].Width = 135;
                dgvBizRuleMapper.Columns["excelFields"].ReadOnly = true; 
            }
        }

        private void PopulateControlForUpdate(string strRulXFile)
        {
            try
            {
                RulesetObject objRuleset = new RulesetObject();

                objRuleset = PrepareListFromRulesetForUpdate(strRulXFile);

                this.txtRulesetName.Text = objRuleset.RulesetName;
                this.txtRulesetDesc.Text = objRuleset.RulesetDescription;
                this.txtAttributeFileName.Text = objRuleset.RulesetAttributeClassName;
                this.txtRulesetFileName.Text = objRuleset.RulesetFileName;
                

            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);
            }
        }

        private void PopulateInitialMappingGridForUpdate(string strRulXFile)
        {
            try
            {
                IList<RulXAttribute> listRulXObjectForUpdate = new List<RulXAttribute>();

                PopulateControlForUpdate(strRulXFile);

                listRulXObjectForUpdate = PrepareListFromRulXForUpdate(strRulXFile);
                //dgvBizRuleMapper.Rows.RemoveAt(0);

                
                
                foreach (RulXAttribute rulXFieldObj in listRulXObjectForUpdate)
                {
                    dgvBizRuleMapper.Rows.Add(rulXFieldObj.RulXFieldName, rulXFieldObj.RulXFieldDirection, rulXFieldObj.RulXFieldDataType, false, rulXFieldObj.IsDerived, rulXFieldObj.IsAllowedNull);
                }

                
                
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);
            }
        }

        private void PopulateInitialMappingGrid(int iSelectOption)
        {
            try
            {
                if (iSelectOption == 0) // from excel input file
                {
                    string _excelPath = txtExcelPath.Text;
                    string _workSheetName = cboSheetName.Text.Trim();
                    //DataSet ds = new DataSet();
                    dgvBizRuleMapper.Columns.Clear();
                    dgvBizRuleMapper.Rows.Clear();

                    dsExcelAtt = objBizRuleMapper.ReadExcelFile(_excelPath, _workSheetName);
                }
                else if (iSelectOption == 1) // from clipboard - copied excel range
                {
                    dsExcelAtt.Tables.Clear();
                    dsExcelAtt.Tables.Add(GetDataFromCopiedExcelRange());
                }

                PrepareGridFrame();

                foreach (DataColumn dc in dsExcelAtt.Tables[0].Columns)
                {
                    if (dc.Caption.Trim().ToUpper().Contains("DERIVED_"))
                    {
                        string strDerivedXmlFieldName = dc.Caption.Substring(8, dc.Caption.Length-8);
                        dgvBizRuleMapper.Rows.Add(dc.Caption, strDerivedXmlFieldName, "Output", "int", false, true);
                        
                    }
                    else
                    {
                        Regex pattern = new Regex("[;,()/\t\r ]|[\n]{2}");
                        string strExpectedvariableName = pattern.Replace(dc.Caption, "");
                        dgvBizRuleMapper.Rows.Add(dc.Caption, strExpectedvariableName, "Input", "string");
                    }
                    

                }
            }
            catch (Exception ex)
            {
                
                MessageBox.Show(ex.Message);
            }

        }

        private DataTable GetDataFromCopiedExcelRange()
        {
            //DataSet dsResult = new DataSet();
            DataTable dtResult = new DataTable(); ;

            if (this.dgvExcelRangeCopy.DataSource!=null)
            {
                dtResult = (DataTable)this.dgvExcelRangeCopy.DataSource; 
            }

            //dsResult.Tables.Add(dtResult);

            return dtResult;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void CreateTempDirForOutput()
        {
            try
            {
                //Guid tempFolderName = Guid.NewGuid();
                //string sysDir = Environment.CurrentDirectory;

                string path = tempOutputDir;

                // Determine whether the directory exists.
                if (!Directory.Exists(path))
                {
                    // Create the directory it does not exist.
                    Directory.CreateDirectory(path);
                    //Copy xsd file.

                }

                //MessageBox.Show(sysDir);
            }
            catch (Exception ex)
            {
                
                MessageBox.Show("Error creating temp folder..." + " [" + ex.Message + "]");
            }
        }

        private void cboSheetName_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                PopulateInitialMappingGrid(0);
                if (dgvBizRuleMapper.Rows.Count > 0)
                {
                    this.btnGenerate.Enabled = true;
                }
                else
                {
                    this.btnGenerate.Enabled = false;
                }

                if (dgvBizRuleMapper.Rows[0].Cells[0].Value == null
                    || string.IsNullOrEmpty(dgvBizRuleMapper.Rows[0].Cells[0].Value.ToString()))
                {
                    dgvBizRuleMapper.Rows.Clear();
                    
                }

                this.lnkRefreshSchema.Enabled = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void BizRuleGenerater_Load(object sender, EventArgs e)
        {
            if (this.DialogOpeningMode == 0)
            {
                //Check if the RulX Files provided are already existing within the currently selected VS project Hierarchy
                SetRulXFileNameAfterValidation();
            }
            else if (this.DialogOpeningMode == 1)
            {
                PrepareGridFrame();
                this.txtExcelPath.Enabled = false;
                this.btnBrowse.Enabled = false;
                this.cboSheetName.Enabled = false;
                this.btnGenerate.Text = "Update RulX";
                this.btnGenerate.Enabled = true;
                this.dgvBizRuleMapper.AllowUserToAddRows = true;

                this.txtRulesetFileName.Text = string.Empty;
                this.txtAttributeFileName.Text = string.Empty;
                this.txtAttributeFileName.Enabled = false;
                this.txtRulesetFileName.Enabled = false;

                PopulateInitialMappingGridForUpdate(this.RulXFileNameForUpdate);
                this.tabOption.TabPages.RemoveAt(1);
            }

        }

        private void txtRulesetFileName_TextChanged(object sender, EventArgs e)
        {
            ////Check if the RulX Files provided are already existing within the currently selected VS project Hierarchy
            //SetRulXFileNameAfterValidation();
            this.txtAttributeFileName.Text = this.txtRulesetFileName.Text;
        }

        private void txtAttributeFileName_TextChanged(object sender, EventArgs e)
        {
            ////Check if the RulX Files provided are already existing within the currently selected VS project Hierarchy
            //SetRulXFileNameAfterValidation();
        }

        private void dgvBizRuleMapper_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (this.dgvBizRuleMapper != null)
            {
                Point point1 = this.dgvBizRuleMapper.CurrentCellAddress;
                if (point1.X == e.ColumnIndex &&
                    point1.Y == e.RowIndex &&
                    e.Button == MouseButtons.Left &&
                    this.dgvBizRuleMapper.EditMode != DataGridViewEditMode.EditProgrammatically)
                {
                    this.dgvBizRuleMapper.BeginEdit(true);
                }
            }
        }

        private void dgvBizRuleMapper_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if(e.ColumnIndex == 4)
            {
                //if (dgvBizRuleMapper.)
                //{
                //    MessageBox.Show("Hi"); 
                //}
            }
        }

        private void dgvBizRuleMapper_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            //dgvBizRuleMapper.Rows[e.RowIndex].ErrorText = "";
            //int newInteger;

            //// Don't try to validate the 'new row' until finished 
            //// editing since there
            //// is not any point in validating its initial value.
            if (dgvBizRuleMapper.Rows[e.RowIndex].IsNewRow) { return; }
            if (e.FormattedValue.ToString().Length == 0)
            {
                
                dgvBizRuleMapper.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "Value cannot be blank";
                MessageBox.Show("Property Name cannot be empty","Microsoft Visual Studio", MessageBoxButtons.OK,MessageBoxIcon.Error);
                e.Cancel = true;
                
            }
            else
            {
                e.Cancel = false;
            }
        }

        private void dgvBizRuleMapper_RowValidating(object sender, DataGridViewCellCancelEventArgs e)
        {
            //DataGridViewRow row = dgvBizRuleMapper.Rows[e.RowIndex];

            //// Don't try to validate the 'new row' until finished 
            //// editing since there
            //// is not any point in validating its initial value.
            //if (dgvBizRuleMapper.Rows[e.RowIndex].IsNewRow) { return; }
            //foreach (DataGridViewColumn colItem in dgvBizRuleMapper.Columns)
            //{
            //    if (colItem.Index == 1)
            //    {
            //        DataGridViewCell cell = row.Cells[colItem.Index];
            //        if (cell.Value == null)
            //        {
                        
            //            cell.ErrorText = "Value cannot be blank";
            //            e.Cancel = true;

            //        }
            //        else
            //        {
            //            cell.ErrorText = string.Empty;
            //            e.Cancel = false;
            //        }  
            //    }
            //}
        }

        private void dgvBizRuleMapper_CellLeave(object sender, DataGridViewCellEventArgs e)
        {
            //DataGridViewRow row = dgvBizRuleMapper.Rows[e.RowIndex];
            //DataGridViewCell cell = row.Cells[e.ColumnIndex];
            //if (cell.Value == null)
            //{
            //    cell.ErrorText = "Value cannot be blank";
            //    e.Cancel = true;
            //}
            //else
            //{
            //    cell.ErrorText = string.Empty;
            //    e.Cancel = false;
            //}
        }

        private void dgvBizRuleMapper_CellValidated(object sender, DataGridViewCellEventArgs e)
        {
            dgvBizRuleMapper.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = null;
            
        }

        private void dgvExcelRangeCopy_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Control && e.KeyCode == Keys.C)
            {
                DataObject d = dgvExcelRangeCopy.GetClipboardContent();
                Clipboard.SetDataObject(d);
                e.Handled = true;
            }
            else if (e.Control && e.KeyCode == Keys.V)
            {
                //DATA TABLE THAT WILL STORE PASTED INFORMATION (AS AN INTERMEDIATE STEP)
                DataTable table_Local = new DataTable();

                //GET DATA FROM CLIPBOARD
                string s = Clipboard.GetText();
                string[] lines = s.Split(new char[2] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

                //ITERATION HEADER-CHECK
                bool IsFirstPass = true;

                foreach (string line in lines)
                {
                    //SPLIT THE ROW
                    string[] cells = line.Split('\t');

                    //IF FIRST PASS, CHECK FOR COLUMN HEADERS
                    if (IsFirstPass)
                    {
                        foreach (string value in cells)
                        { table_Local.Columns.Add(value); }
                        //
                        IsFirstPass = false;
                    }
                    else
                    {
                        DataRow newRow = table_Local.NewRow();
                        newRow.ItemArray = cells;
                        table_Local.Rows.Add(newRow);
                    }
                }
                this.dgvExcelRangeCopy.DataSource = table_Local;

            }
        }

        private void dgvExcelRangeCopy_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            //PopulateInitialMappingGrid(1);

            if (dgvBizRuleMapper.Rows.Count > 0)
            {
                this.btnGenerate.Enabled = true;
            }
            else
            {
                this.btnGenerate.Enabled = false;
            }
            this.lnkRefreshSchema.Enabled = true;
        }

        private void tabOption_TabIndexChanged(object sender, EventArgs e)
        {
            //if (tabOption.TabIndex == 0)
            //{
            //    //this.dgvExcelRangeCopy.DataSource = null;
            //    ClearDataGridControl(this.dgvExcelRangeCopy);
            //    ClearDataGridControl(this.dgvBizRuleMapper);
            //}

            
        }

        private void ClearDataGridControl(DataGridView dgv)
        {
            if (dgv.RowCount>0 && dgv.Columns.Count>0)
            {
                dgv.Rows.Clear();
                dgv.Columns.Clear(); 
            }
        }

        private void tabOption_SelectedIndexChanged(object sender, EventArgs e)
        {
            //ClearDataGridControl(this.dgvExcelRangeCopy);
            //ClearDataGridControl(this.dgvBizRuleMapper);

            this.dgvExcelRangeCopy.DataSource = null;
            if (tabOption.SelectedTab.Text.Equals("Use Excel File"))
            {
                iRuleSelectionOption = 0;
            }
            else if (tabOption.SelectedTab.Text.Equals("Copy Range from Excel"))
            {
                iRuleSelectionOption = 1;
            }
        }

        private void lnkRefreshSchema_Click(object sender, EventArgs e)
        {
            

            if (iRuleSelectionOption == 0)
            {
                PopulateInitialMappingGrid(0);
            }
            else if (iRuleSelectionOption == 1)
            {
                PopulateInitialMappingGrid(1);
                if (dgvBizRuleMapper.Rows.Count > 0)
                {
                    this.btnGenerate.Enabled = true;
                }
                else
                {
                    this.btnGenerate.Enabled = false;
                }
            }
        }

        
    }

    public class RulXEventArgs : EventArgs
    {
        public string RulXFileName { get; set; }

        public RulXEventArgs(string sFileName)
        {
            RulXFileName = sFileName;
        }
    }
}
